#include <stdio.h>
#include <termios.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

/* 设置串口参数的函数 */
int set_uart(int fd, int speed, int bits, char check, int stop) {
    struct termios newtio, oldtio;

    // 步骤一：保存原来的串口配置
    if(tcgetattr(fd, &oldtio) != 0) {
        printf("tcgetattr oldtio error\n");
        return -1;
    }

    bzero(&newtio, sizeof(newtio));
    
    // 步骤二：设置控制模式标志
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    // 步骤三：设置数据位
    switch(bits) {
        case 7:
            newtio.c_cflag |= CS7;
            break;
        case 8:
            newtio.c_cflag |= CS8;
            break;
    }
    
    // 步骤四：设置奇偶校验位
    switch(check) {
        case 'O': // 偶校验位
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'E': // 奇校验位
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'N': // 无校验
            newtio.c_cflag &= ~PARENB;
            break;
    }
    
    // 步骤五：设置波特率
    switch(speed) {
        case 9600:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
        case 115200:
            cfsetispeed(&newtio, B115200);
            cfsetospeed(&newtio, B115200);
            break;
    }
    
    // 步骤六：设置停止位
    switch(stop) {
        case 1:
            newtio.c_cflag &= ~CSTOPB; // 1位停止位
            break;
        case 2:
            newtio.c_cflag |= CSTOPB; // 2位停止位
            break;
    }
    
    // 步骤七：刷新输入队列
    tcflush(fd, TCIFLUSH);
    
    // 步骤八：设置配置立刻生效
    if (tcsetattr(fd, TCSANOW, &newtio) != 0) {
        printf("tcsetattr newtio error\n");
        return -2;
    }
    
    return 0;
}

int main(int argc, char *argv[]) {
    int fd;
    char buf[128];
    int count;
    
    // 步骤九：打开串口设备
    fd = open("/dev/ttyS9", O_RDWR | O_NOCTTY | O_NDELAY);
    
    if (fd < 0) {
        printf("open error \n");
        return -1;
    }

    // 设置串口参数
    set_uart(fd, 115200, 8, 'N', 1);
    
    // 写入数据
    write(fd, argv[1], strlen(argv[1]));
    sleep(1);
    
    // 读取数据
    count = read(fd, buf, sizeof(buf));
    buf[count] = '\0';
    
    // 输出读取的数据
    printf("read message is %s\n", buf);
    
    // 关闭串口设备
    close(fd);
    
    return 0;
}
